import 'dart:async';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_widget/src/widget/effect/clip_widget.dart';
import 'package:flutter_widget/src/widget/indicator/page_indicator.dart';

typedef OnBannerClickListener<D> = void Function(int index, D itemData);
typedef BuildShowView<D> = Widget Function(int index, D itemData);

const IntegerMax = 0x7fffffff;

/*
eg:
BannerView(
  height: 100,
  data: provider.banner,
  buildShowView: (index, data) {
    return Image.asset data[index]);
  },
  onBannerClickListener: (index, data) {
    print(index);
  },
),
* */
class BannerWidget<T> extends StatefulWidget {
  final OnBannerClickListener<T>? onBannerClickListener;
  final int delayTime; //秒，延迟多少秒进入下一页
  final int scrollTime; //毫秒，滑动需要秒数
  final double height;
  final double? width;
  final double marginLeft;
  final double marginRight;
  final double marginTop;
  final double marginBottom;

  // final double paddingVertical;
  // final double paddingHorizontal;
  final double radius;
  final Color backgroundColor;
  final List<T> data;
  final BuildShowView<T> buildShowView;
  final bool isShowIndicator; //内部是否展示页面指示器
  final bool isShowIndicatorOut; //是否显示在外面
  final bool enableScrollWhenSingle; //只有一个是否可以划动
  final int autoNextMinCount; //自动播放的最小数量，>=自动播放, 默认1
  final double? viewportFraction;
  final bool? padEnds;
  final bool? reverse;
  final ValueChanged<int>? onPageChanged;

  const BannerWidget({
    Key? key,
    required this.data,
    required this.buildShowView,
    this.onBannerClickListener,
    this.onPageChanged,
    this.delayTime = 4,
    this.scrollTime = 450,
    required this.height,
    this.width,
    this.marginLeft = 0,
    this.marginRight = 0,
    this.marginTop = 0,
    this.marginBottom = 0,
    // this.paddingVertical = 0,
    // this.paddingHorizontal = 0,
    this.radius = 4,
    this.backgroundColor = Colors.transparent,
    this.isShowIndicator = false,
    this.isShowIndicatorOut = false,
    this.autoNextMinCount = 1,
    this.enableScrollWhenSingle = false,
    this.viewportFraction,
    this.padEnds,
    this.reverse,
  }) : super(key: key);

  @override
  State<StatefulWidget> createState() => BannerWidgetState<T>();
}

class BannerWidgetState<T> extends State<BannerWidget> {
  late final pageController;
  Timer? timer;
  int _currentPageIndex = 0;

  BannerWidgetState() {
//    print(widget.delayTime);
  }

  @override
  void dispose() {
    clearTimer();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    pageController = PageController(
      initialPage: IntegerMax ~/ 2,
      viewportFraction: widget.viewportFraction ?? 1.0,
    );
    resetTimer();
  }

  resetTimer() {
    if (widget.data.length < widget.autoNextMinCount) {
      return;
    }
    clearTimer();
    timer = Timer.periodic(Duration(seconds: widget.delayTime),
        (Timer timer) {
      if (pageController.positions.isNotEmpty == true) {
        var i = pageController.page!.ceil() + 1;
        pageController.animateToPage(
          i == 3 ? 0 : i,
          duration: Duration(milliseconds: widget.scrollTime),
          curve: Curves.linear,
        );
      }
    });
  }

  clearTimer() {
    if (timer != null) {
      timer!.cancel();
      timer = null;
    }
  }

  @override
  Widget build(BuildContext context) {
    var body = Container(
      height: widget.height,
      width: widget.width,
      color: widget.backgroundColor,
      padding: EdgeInsets.only(
        top: widget.marginTop,
        bottom: widget.marginBottom,
        left: widget.marginLeft,
        right: widget.marginRight,
      ),
      child: GestureDetector(
        dragStartBehavior: DragStartBehavior.down,
        onTap: (widget.onBannerClickListener == null)
            ? null
            : () {
                int count = widget.data.length;
                if (widget.enableScrollWhenSingle == false && count == 1) {
                  widget.onBannerClickListener!(
                    0,
                    widget.data[0],
                  );
                } else {
                  widget.onBannerClickListener!(
                    pageController.page!.round() % count,
                    widget.data[pageController.page!.round() % count],
                  );
                }
              },
        onTapDown: (details) {
          clearTimer();
        },
        onTapUp: (details) {
          resetTimer();
        },
        onTapCancel: () {
          resetTimer();
        },
        child: ClipWidget(
          radius: widget.radius,
          child: widget.data.isEmpty
              ? null
              : (widget.enableScrollWhenSingle == false &&
                      widget.data.length == 1)
                  ? widget.buildShowView(
                      (0 % widget.data.length),
                      widget.data[0],
                    )
                  : Stack(
                      children: [
                        Positioned.fill(
                          child: PageView.builder(
                            padEnds: widget.padEnds ?? true,
                            reverse: widget.reverse ?? false,
                            controller: pageController,
                            physics: const PageScrollPhysics(
                              parent: ClampingScrollPhysics(),
                            ),
                            itemBuilder: (BuildContext context, int index) {
                              T item = widget.data[index % widget.data.length];
                              return widget.buildShowView(
                                (index % widget.data.length),
                                item,
                              );
                            },
                            itemCount: IntegerMax,
                            onPageChanged: (int index) {
                              setState(() {
                                _currentPageIndex = index % (widget.data.length);
                                if (widget.onPageChanged != null) {
                                  widget.onPageChanged!(index % (widget.data.length));
                                }
                              });
                            },
                          ),
                        ),
                        if (widget.isShowIndicator == true)
                          Positioned(
                            bottom: 9,
                            left: 0,
                            right: 0,
                            child: PageIndicator(
                              itemCount: widget.data.length,
                              selectItem: _currentPageIndex,
                            ),
                          )
                      ],
                    ),
        ),
      ),
    );
    if (widget.isShowIndicatorOut == true) {
      ///不使用
      return Column(
        children: [
          body,
          Visibility(
            visible: widget.isShowIndicatorOut,
            child: PageIndicator(
              itemCount: widget.data.length,
              selectItem: _currentPageIndex,
            ),
          ),
        ],
      );
    }
    return body;
  }
}
